package com.treasure.mall.biz.service.core.user.impl;

import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import com.treasure.mall.biz.config.wechat.WeChatConfig;
import com.treasure.mall.biz.dto.user.LoginDTO;
import com.treasure.mall.biz.dto.wechat.CreateWxaCodeDTO;
import com.treasure.mall.biz.entity.user.WechatUser;
import com.treasure.mall.biz.repository.user.WechatUserRepository;
import com.treasure.mall.biz.service.core.user.WeChatService;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.exception.ApiException;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.Objects;

/**
 * 
 * +---------------------------------------------------------
 * * @package: com.treasure.mall.biz.service.core.user.impl
 * * @author: guomw (guomwchen@foxmail.com)
 * * @date: 2020/6/11 12:46
 * * @since: V1.0.0
 * +---------------------------------------------------------
 * 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的
 * Copyright 2019-2022 com.treasure.mall.biz.service.core.user.impl Inc. All rights reserved.
 */
@Service
public class WeChatServiceImpl implements WeChatService {
    @Resource
    private WechatUserRepository wechatUserRepository;

    @Autowired
    private WeChatConfig weChatConfig;

    private WxMaService getWxMaService() {
        WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
        config.setAppid(weChatConfig.getMiniAppId());
        config.setSecret(weChatConfig.getMiniAppSecret());
        config.setMsgDataFormat("JSON");
        WxMaService wxMaService = new WxMaServiceImpl();
        wxMaService.setWxMaConfig(config);
        return wxMaService;
    }


    @Override
    public WechatUser loginByCode(String code) {
        try {
            WxMaService wxMaService = getWxMaService();
            WxMaUserService wxMaUserService = wxMaService.getUserService();
            // 获取微信用户session
            WxMaJscode2SessionResult session = wxMaUserService.getSessionInfo(code);
            if (null == session) {
                throw new ApiException("login handler error");
            }
            WechatUser wechatUser = StringUtils.isNotBlank(session.getUnionid()) ? wechatUserRepository.findFirstByUnionId(session.getUnionid()) : wechatUserRepository.findFirstByAppIdAndOpenId(weChatConfig.getMiniAppId(), session.getOpenid());
            if (wechatUser != null) {
                wechatUser.setUnionId(session.getUnionid());
                wechatUser.setOpenId(session.getOpenid());
                wechatUserRepository.save(wechatUser);
                return wechatUser;
            }

        } catch (Exception e) {

        }
        return null;
    }


    /**
     * 小程序登录
     *
     * @param dto
     * @return
     */
    @Override
    public WechatUser login(LoginDTO dto) throws WxErrorException {
        WxMaService wxMaService = getWxMaService();
        WxMaUserService wxMaUserService = wxMaService.getUserService();
        // 获取微信用户session
        WxMaJscode2SessionResult session = wxMaUserService.getSessionInfo(dto.getCode());
        if (null == session) {
            throw new ApiException("login handler error");
        }
        // 解密用户信息
        WxMaUserInfo wxUserInfo = wxMaUserService.getUserInfo(session.getSessionKey(),
                dto.getUserInfoEncryptedData().getEncryptedData(), dto.getUserInfoEncryptedData().getIv());
        if (null == wxUserInfo) {
            throw new ApiException("wx user not exist");
        }

        // 解密手机号码信息
        WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxMaUserService.getPhoneNoInfo(session.getSessionKey(),
                dto.getPhoneInfoEncryptedData().getEncryptedData(), dto.getPhoneInfoEncryptedData().getIv());
        if (Objects.isNull(wxMaPhoneNumberInfo) || StringUtils.isBlank(wxMaPhoneNumberInfo.getPhoneNumber())) {
            // 解密手机号码信息错误
            throw new ApiException("not phoneNumber");
        }

        WechatUser wechatUser = getWechatUser(wxUserInfo, session.getSessionKey());
        wechatUser.setPurePhoneNumber(wxMaPhoneNumberInfo.getPurePhoneNumber());
        wechatUser.setPhoneNumber(wxMaPhoneNumberInfo.getPhoneNumber());

        WechatUser po = wechatUserRepository.findTopByPhoneNumber(wxMaPhoneNumberInfo.getPhoneNumber());
        if (po != null) {
            wechatUser.setId(po.getId());
            wechatUser.setOpenId(wxUserInfo.getOpenId());
        }
        wechatUserRepository.save(wechatUser);
        return wechatUser;
    }

    private WechatUser getWechatUser(WxMaUserInfo wxUserInfo, String sessionKey) {
        WechatUser wechatUser = new WechatUser();
        wechatUser.setAppId(weChatConfig.getMiniAppId());
        wechatUser.setOpenId(wxUserInfo.getOpenId());
        wechatUser.setMiniSessionKey(sessionKey);
        wechatUser.setUnionId(wxUserInfo.getUnionId());
        wechatUser.setAvatarUrl(wxUserInfo.getAvatarUrl());
        wechatUser.setCity(wxUserInfo.getCity());
        wechatUser.setCountry(wxUserInfo.getCountry());
        wechatUser.setNickname(wxUserInfo.getNickName());
        wechatUser.setProvince(wxUserInfo.getProvince());
        if (StringUtils.isNotBlank(wxUserInfo.getGender())) {
            wechatUser.setSex(wxUserInfo.getGender().toUpperCase().equals("GENDER") ? 0 : 1);
        } else {
            wechatUser.setSex(0);
        }
        return wechatUser;
    }

    /**
     * 生成二维码
     *
     * @param dto
     * @return
     * @throws WxErrorException
     */
    @Override
    public File createWxaCodeUnlimit(CreateWxaCodeDTO dto) {
        WxMaQrcodeService wxService = getWxMaService().getQrcodeService();
        try {
            return wxService.createWxaCodeUnlimit(dto.getScene(), dto.getPage(), dto.getWidth(), dto.isAutoColor(), null, dto.isHyaline());
        } catch (WxErrorException e) {
            throw new ApiException(ApiResult.error(e.getMessage()));
        }
    }

}
